package com.rss.inbound.processors;

import java.net.URL;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.apache.log4j.Logger;
import org.springframework.batch.item.ItemProcessor;

import com.rss.inbound.beans.RssEntry;
import com.rss.inbound.beans.RssSrc;
import com.rss.inbound.dao.RssEntryDAO;
import com.rss.inbound.factories.RssMapperFactory;
import com.rss.inbound.mappers.RssMapper;
import com.sun.syndication.feed.synd.SyndEntry;
import com.sun.syndication.feed.synd.SyndFeed;
import com.sun.syndication.io.SyndFeedInput;
import com.sun.syndication.io.XmlReader;

public class RssSourceDataProcessor implements
	ItemProcessor<RssSrc, List<RssEntry>>
{
    Logger		   log	 = Logger.getLogger(getClass());
    private RssEntryDAO      rssEntryDao = null;
    private RssMapperFactory mapperFactory;

    @SuppressWarnings("unchecked")
    @Override
    public List<RssEntry> process(RssSrc rssSrc) throws Exception
    {
		URL feedSource = new URL(rssSrc.getRssSrcDwnldLnk());
		SyndFeedInput input = new SyndFeedInput();
		SyndFeed feed = input.build(new XmlReader(feedSource));
		List<RssEntry> rssEntries = new ArrayList<RssEntry>();
	
		RssMapper rssMapper = mapperFactory.createInstance(rssSrc
			.getRssSrcTtl());
		if (rssMapper != null)
		{
		    log.info("Processing RSS Source ==> " + rssSrc.getRssSrcTtl());
	
		    List<SyndEntry> engadgetEntries = feed.getEntries();
	
		    log.info("No. of active entries today for Engadget - "
			    + engadgetEntries.size());
	
		    for (SyndEntry engadgetEntry : engadgetEntries)
		    {
				boolean isDuplicate = checkForDupeEntry(engadgetEntry,
					rssSrc.getRssSrcTtl());
		
				if (!isDuplicate)
				{
				    RssEntry entry = rssMapper.mapRssEntry(engadgetEntry,
					    rssSrc);
				    rssEntries.add(entry);
				}
		    }
		}

		return rssEntries;
    }

    private boolean checkForDupeEntry(SyndEntry rssEntry, String rssSourceTitle)
    {
		boolean isDupe = false;
		String rssEntryLink = rssEntry.getUri();
		List<RssEntry> matchingRssEntries = rssEntryDao
			.findMatchingEntries(rssEntryLink);
	
		for (RssEntry matchingRssEntry : matchingRssEntries)
		{
		    String existingEntryDesc = null;
	
		    if (rssSourceTitle.equalsIgnoreCase("Engadget"))
		    {
				// For engadget.com the entry description and content are the
				// same in the RSS Feed!
				existingEntryDesc = new String(matchingRssEntry.getCntn());
		    }
		    else if (rssSourceTitle.equalsIgnoreCase("TechCrunch"))
		    {
				// For techcrunch.com the entry description and content are NOT
				// the same in the RSS Feed!
				existingEntryDesc = new String(matchingRssEntry.getDesc());
		    }
	
		    if (existingEntryDesc.equalsIgnoreCase(rssEntry.getDescription()
			    .getValue()))
		    {
				log.info("Found an existing entry with the same link and content...Hence marking this one to DUPE status");
				isDupe = true;
		    }
		    else
		    {
				log.info("Updating the Entry's Content - Since there is only change in content with in the same link...");
				matchingRssEntry.setCntn(rssEntry.getDescription().getValue()
					.getBytes());
				matchingRssEntry.setLastModBy("RssDownloaderBatch");
				matchingRssEntry.setLastModDttm(new Date());
				matchingRssEntry.setPubDttm(rssEntry.getPublishedDate());
				rssEntryDao.updateContent(matchingRssEntry);
				log.info("Done updating the Entry's Content...");
		
				// Setting dupe flag to true to make sure another entry is not
				// added to the database
				log.info("Setting entry to DUPE status...for not adding another entry to the DB");
				isDupe = true;
		    }
		}
		return isDupe;
    }

    public void setMapperFactory(RssMapperFactory mapperFactory)
    {
    	this.mapperFactory = mapperFactory;
    }

    public void setRssEntryDao(RssEntryDAO rssEntryDao)
    {
    	this.rssEntryDao = rssEntryDao;
    }
}
